/* $Id:army.cc $ */
/*
   Copyright (C) 2007 by Jurjen Stellingwerff <jurjen@stwerff.xs4all.nl>
   Part of the Moros Project http://moros.sourceforge.net/

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License version 3.
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY.

   See the COPYING file for more details.
*/

#define DEBUG_ROUTINE "army"

#include <sstream>
#include <fstream>
#include "../general/util.h"
#include "../general/log.h"
#include "../general/channel.h"
#include "army.h"
#include "unit.h"
#include "item.h"
#include "unit.h"
#include "item.h"
#include "../general/general.h"

army::army() {
    name="";
    members=map<string,class members>();
    goods=map<string,class material>();
    members_wanted=map<string,class members>();
    goods_wanted=map<string,class material>();
    location=0;
}

// Field : name

const string army::getName() const { return name; }
void army::setName(const string v) { name=v; }

// Field : members

class members& army::getMembers(const string v) { return members[v]; }
map<string,class members>& army::listMembers() { return members; }
void army::setMembers(class members &v) {
    members[v.getMember().getName()]=v;
}
void army::delMembers(const string v) { members.erase(v); }
const bool army::isMembers(const string v) const { return members.count(v)>0; }

// Field : goods

class material& army::getGoods(const string v) { return goods[v]; }
list<class material>& army::listGoods() {
    static list<class material> res;
    res.clear();
    loopMap(goods,v,class material) {
        res.push_back(*v);
    }
    res.sort();
    return res;
}
void army::setGoods(class material &v) {
    goods[v.getItem().getName()]=v;
}
void army::delGoods(const string v) { goods.erase(v); }
const bool army::isGoods(const string v) const { return goods.count(v)>0; }

// Field : members_wanted

class members& army::getMembers_wanted(const string v) { return members_wanted[v]; }
map<string,class members>& army::listMembers_wanted() { return members_wanted; }
void army::setMembers_wanted(class members &v) {
    members_wanted[v.getMember().getName()]=v;
}
void army::delMembers_wanted(const string v) { members_wanted.erase(v); }
const bool army::isMembers_wanted(const string v) const { return members_wanted.count(v)>0; }

// Field : goods_wanted

class material& army::getGoods_wanted(const string v) { return goods_wanted[v]; }
list<class material>& army::listGoods_wanted() {
    static list<class material> res;
    res.clear();
    loopMap(goods_wanted,v,class material) {
        res.push_back(*v);
    }
    res.sort();
    return res;
}
void army::setGoods_wanted(class material &v) {
    goods_wanted[v.getItem().getName()]=v;
}
void army::delGoods_wanted(const string v) { goods_wanted.erase(v); }
const bool army::isGoods_wanted(const string v) const { return goods_wanted.count(v)>0; }

// Field : location

const int army::getLocation() const { return location; }
void army::setLocation(const int  v) { location=v; }
const string army::showLocation() const {
    stringstream res;
    res << "(" << (location & 0xffff) << "," << (location << 16) << ")";
    return res.str();
}

void army::save(class channel &ch) {
    ch.write("army", "");
    ch.write("n", getName());
    loopArmyMembers(this, s_members) {
        s_members->save(ch);
    }
    loopArmyGoods(this, s_goods) {
        s_goods->save(ch);
    }
    loopArmyMembers_wanted(this, s_members_wanted) {
        s_members_wanted->save(ch);
    }
    loopArmyGoods_wanted(this, s_goods_wanted) {
        s_goods_wanted->save(ch);
    }
    ch.write("l", getLocation());
}

void army::load(class channel &ch) {
    if (ch.key=="n" || ch.key=="name") { setName(ch.value); ch.next(); }
    while (ch.key=="members" || ch.key=="members") {
        ch.next();
        class members rec;
        rec.load(ch);
        setMembers(rec);
    }
    while (ch.key=="material" || ch.key=="goods") {
        ch.next();
        class material rec;
        rec.load(ch);
        setGoods(rec);
    }
    while (ch.key=="members" || ch.key=="members_wanted") {
        ch.next();
        class members rec;
        rec.load(ch);
        setMembers_wanted(rec);
    }
    while (ch.key=="material" || ch.key=="goods_wanted") {
        ch.next();
        class material rec;
        rec.load(ch);
        setGoods_wanted(rec);
    }
    if (ch.key=="l" || ch.key=="location") { setLocation(atoi(ch.value.c_str())); ch.next(); }
}

void army::xml(ofstream &f, int l, int r) {
    f << ncpy(l, "  ") << "<army name=\"" << xml_encode(getName()) <<
    "\" location_x=\"" << (getLocation() & 0xffff) <<
    "\" location_y=\"" << (getLocation() << 16) <<
    "\">" << endl;
    if (r==0) {
        loopArmyMembers(this, s_members) {
            s_members->xml(f,l+1);
        }
        loopArmyGoods(this, s_goods) {
            s_goods->xml(f,l+1);
        }
        loopArmyMembers_wanted(this, s_members_wanted) {
            s_members_wanted->xml(f,l+1);
        }
        loopArmyGoods_wanted(this, s_goods_wanted) {
            s_goods_wanted->xml(f,l+1);
        }
    }
    f << ncpy(l, "  ") << "</army>" << endl;
}

// Repository

armyRepository army_repo;

class army& armyRepository::getArmy(const string v) { return armys[v]; }
void armyRepository::setArmy(class army& v) {
    if (v.getName()=="") throw unnamed();
    armys[v.getName()]=v;
}
map<string,class army>& armyRepository::listArmy() { return armys; }
void armyRepository::delArmy(const string v) { armys.erase(v); }
const bool armyRepository::isArmy(const string v) const { return armys.count(v)>0; }
void armyRepository::save(class channel &ch) {
    loopArmys(rec) {
        rec->save(ch);
    }
}

bool armyRepository::load(class channel &ch) {
    if (ch.key=="army") {
        ch.next();
        class army rec;
        rec.load(ch);
        setArmy(rec);
        return true;
    }
    return false;
}
